{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "498d70fa",
   "metadata": {},
   "source": [
    "**<font color = black size=6>实验四:模型评估</font>**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa5c5483",
   "metadata": {},
   "source": [
    "**<font color = blue size=4>第一部分:数据集划分</font>**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9fa3ad13",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import math\n",
    "import matplotlib as mpl\n",
    "import warnings\n",
    "import random\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "869f21ce",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">给定一个完整的数据集，尚未划分训练集和测试集，我们需要手动实现训练集和测试集的划分:</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ee0eb93",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">我们继续使用iris数据集(iris.csv)，这次我们引入了具有4个特征 (花萼长度($x_1$)，花萼宽度 ($x_2$),花瓣长度 ($x_3$),花瓣宽度 ($x_4$))和两个标签 (Setosa，Versicolour)的100个样本数据，其中每类标签的样本占50%。我们需要将其划分为训练集和测试集，其中测试集中的样本数量占总数量的30%(也就是30个)，且测试集中每个标签的样本各占50%</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e6dc88ab",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">1) 留出法</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "031ac8a2",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">我们通过随机选择样本的方式将数据分割为训练集和测试集，并保持两种标签的数据的数量一致</span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f5a2eb0",
   "metadata": {},
   "outputs": [],
   "source": [
    "#通过pandas将csv文件转换为dataframe格式后进行操作\n",
    "df = pd.read_csv('iris.csv')\n",
    "\n",
    "#将label标签内容从字符串替换为数值\n",
    "df['Species'] = df['Species'].map({'setosa': 0, 'virginica': 1}).fillna(-1)\n",
    "\n",
    "# 获取特征和标签列\n",
    "features = df.iloc[:, :-1]\n",
    "labels = df.iloc[:, -1]\n",
    "\n",
    "# 计算每个类别需要分配给测试集的样本数量的比例，假设为 30%\n",
    "test_ratio = 0.3\n",
    "\n",
    "# 计算每个类别需要分配给测试集的样本数量\n",
    "test_samples_per_class = (labels.value_counts() * test_ratio).astype(int)\n",
    "\n",
    "# 初始化测试集和训练集\n",
    "train_data = pd.DataFrame()\n",
    "test_data = pd.DataFrame()\n",
    "\n",
    "# 根据标签的分布进行采样\n",
    "for label, count in test_samples_per_class.items():\n",
    "    class_samples = df[df['Species'] == label].sample(n=count, random_state=42)\n",
    "    test_data = test_data.append(class_samples)\n",
    "    train_data = train_data.append(df[df['Species'] == label].drop(class_samples.index))\n",
    "\n",
    "# 获取训练集和测试集的特征和标签\n",
    "train_features = train_data.iloc[:, :-1]\n",
    "train_labels = train_data.iloc[:, -1]\n",
    "test_features = test_data.iloc[:, :-1]\n",
    "test_labels = test_data.iloc[:, -1]\n",
    "\n",
    "# 打印训练集和测试集大小\n",
    "print(\"Train data number: \", len(train_data))\n",
    "print(\"Test data number: \", len(test_data))\n",
    "\n",
    "#打印训练集和测试集\n",
    "print(\"Train data : \", np.array(train_data))\n",
    "print(\"Test data : \", np.array(test_data))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4439e70",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">2) 交叉验证法</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94e03583",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">我们将数据集分割为k个大小相等且标签数量类似的子数据集，每个迭代中选取一个子数据集作为测试集，剩余k-1个组成训练集，并保持两种标签的数据的数量一致</span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "583cafc3",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv('iris.csv')\n",
    "\n",
    "#将label标签内容从字符串替换为数值\n",
    "df['Species'] = df['Species'].map({'setosa': 0, 'virginica': 1}).fillna(-1)\n",
    "\n",
    "# 获取特征和标签列\n",
    "features = df.iloc[:, :-1]\n",
    "labels = df.iloc[:, -1]\n",
    "\n",
    "# 将数据按照标签分为两类\n",
    "class_0_samples = df[df['Species'] == 0]\n",
    "class_1_samples = df[df['Species'] == 1]\n",
    "\n",
    "# 将每一类别的样本随机排序\n",
    "class_0_samples = class_0_samples.sample(frac=1, random_state=42)\n",
    "class_1_samples = class_1_samples.sample(frac=1, random_state=42)\n",
    "\n",
    "\n",
    "# 进行 k 折交叉验证\n",
    "k = 5\n",
    "\n",
    "# 初始化训练集和测试集的列表\n",
    "train_data = []\n",
    "test_data = []\n",
    "\n",
    "for i in range(k):\n",
    "    # 初始化当前折的训练集和测试集\n",
    "    train_fold = pd.DataFrame()\n",
    "    test_fold = pd.DataFrame()\n",
    "\n",
    "    # 计算当前折中每个类别的样本数量\n",
    "    class_0_fold_size = len(class_0_samples) // k\n",
    "    class_1_fold_size = len(class_1_samples) // k\n",
    "    \n",
    "\n",
    "    # 添加当前折中每个类别的样本到测试集\n",
    "    test_fold = test_fold.append(class_0_samples[i * class_0_fold_size: (i + 1) * class_0_fold_size])\n",
    "    test_fold = test_fold.append(class_1_samples[i * class_1_fold_size: (i + 1) * class_1_fold_size])\n",
    "    \n",
    "    # 添加剩余样本到训练集\n",
    "    train_fold = df.drop(test_fold.index)\n",
    "\n",
    "    # 打乱训练集和测试集的顺序，以便更好的随机性\n",
    "    train_fold = train_fold.sample(frac=1, random_state=42)\n",
    "    test_fold = test_fold.sample(frac=1, random_state=42)\n",
    "\n",
    "    # 将当前折的训练集和测试集添加到列表\n",
    "    train_data.append(train_fold)\n",
    "    test_data.append(test_fold)\n",
    "\n",
    "# 打印每一折的测试集索引，可以看到均为不重复样本\n",
    "for i in range(k):\n",
    "    print(\"第\", i+1, \"折的测试集: \", (test_data[i].index))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7eb3da69",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">3) 自助法</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c3824cc",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">我们使用有放回采样的方式，每次选取选取一个样本加入到训练集，抽取样本数量(100)次后，将未被选择的样本组成测试集</span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4d61aa90",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv('iris.csv')\n",
    "\n",
    "#将label标签内容从字符串替换为数值\n",
    "df['Species'] = df['Species'].map({'setosa': 0, 'virginica': 1}).fillna(-1)\n",
    "\n",
    "# 获取特征和标签列\n",
    "features = df.iloc[:, :-1]\n",
    "labels = df.iloc[:, -1]\n",
    "\n",
    "# 创建自助样本集\n",
    "num_samples = df.shape[0]\n",
    "train_data = []\n",
    "test_data = []\n",
    "\n",
    "for i in range(num_samples):\n",
    "    index = random.randint(0, num_samples-1)\n",
    "    train_data.append(df.iloc[index])\n",
    "\n",
    "# 创建测试集（排除训练集中已存在的样本）\n",
    "for _, row in df.iterrows():\n",
    "    is_in_train_data = False\n",
    "    for train_row in train_data:\n",
    "        if row.equals(train_row):\n",
    "            is_in_train_data = True\n",
    "            break\n",
    "    if not is_in_train_data:\n",
    "        test_data.append(row)\n",
    "\n",
    "# 打印训练集和测试集大小\n",
    "print(\"训练集大小: \", len(train_data))\n",
    "print(\"测试集大小: \", len(test_data))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "defc35cf",
   "metadata": {},
   "source": [
    "**<font color = blue size=4>第二部分:性能度量</font>**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0bad6882",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">1) 回归任务:</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2947d07a",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">均方误差(MSE): 计算模型的预测 $\\hat{Y}$ 与真实标签 $Y$ 的接近程度</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a2a2f92",
   "metadata": {},
   "source": [
    "给定一组测试集样本$D$ = \\{$(x_1,y_1),(x_2,y_2), ... ,(x_m,y_m)$\\},其中$x_i$为样本$i$的特征值,$y_i$为样本$i$的标签值, $f$为训练的模型,该模型$f$在$D$的均方误差为$$E(f;D) = \\frac{1}{m}\\sum_{i=1}^{m}{(f(x_i)-y_i)^2}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34471ad3",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">2)分类任务:</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "839671e7",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">2.1)错误率: 分类错误样本占比</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b3765a7",
   "metadata": {},
   "source": [
    "给定一组测试集样本$D$ = \\{$(x_1,y_1),(x_2,y_2), ... ,(x_m,y_m)$\\}, 其中$x_i$为样本$i$的特征值, $y_i$为样本$i$的真实标签, $f$为训练的模型, $f(x_i)$为样本$i$的预测标签, 该模型$f$在$D$的错误率为$$E(f;D) = \\frac{1}{m}\\sum_{i=1}^{m}{Ⅱ(f(x_i)\\neq y_i)}$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7730363",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">2.2)精确率: 分类正确样本占比</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f8bafc4",
   "metadata": {},
   "source": [
    "给定一组测试集样本$D$ = \\{$(x_1,y_1),(x_2,y_2), ... ,(x_m,y_m)$\\}, 其中$x_i$为样本$i$的特征值, $y_i$为样本$i$的真实标签, $f$为训练的模型, $f(x_i)$为样本i的预测标签, 该模型$f$在$D$的精度为$$acc(f;D) = \\frac{1}{m}\\sum_{i=1}^{m}{Ⅱ(f(x_i) = y_i)} = 1 - E(f;D)$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0406841",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">2.3)查准率和查全率: 正例被预测出来的比率和预测出来的正例中正确的比率</span>"
   ]
  },
  {
   "attachments": {
    "1.png": {
     "image/png": "iVBORw0KGgoAAAANSUhEUgAAA10AAAEzCAMAAAGKw6n4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURf///wAAABAQEPf395yclNbWzoyMjObe5lJSSsW9xe/v7ykpKUJKSgAACEJCOt7e3hkQGVpjYyEhIVpSUr29vWtra87FzikxMbW1tZylnHNzczE6OpSUlHuEhHtze6WtrYQZtb1S5oRS5jpSGb0Z5oQZ5rXm5nPv5u9S3nPvre8Z3u+M3nPF5nPFrbVSEHNSELUZEHMZELWl3lLva1Kla1LvIVKlIRnvaxmlaxnvIRmlIRlSjBkZjO+93u9ape9aQhk6Wu8Zpe8ZQu+cpe+cQu9ac+9aEO8Zc+8ZEO+cc++cEBkQWrVSMXNSMbUZMXMZMXOMnO/epe/eQoyEOu/ec+/eEIyEEEpSjEoZjIzmWozmEIy1Woy1EBDO5hCE5hDOrRCErRBKEMXmrRlSrRkZrRlS7xkZ76XmrRlSzhkZzq1StXNSta0Ztb2EOjoQEL2EEL3mWr3mEL21Wr21EKVShELO5kKE5kLOrUKEraUZhKVSWqUZWlLOWlKEWlLOEFKEEBnOWhmEWhnOEBmEEEpS70pSrUoZrUoZ74zme4zmMYy1e4y1MRDv5hCl5hDvrRClrUpSzkoZzrWEhBBKMYSM74SMxcWE3mOM72OMxaWE3sWEY5yEY1IQWs5StZRStc4Ztb3me73mMb21e721McVShELv5kKl5kLvrUKlrcUZhMVSWsUZWlLOe1KEe1LOMVKEMRnOexmEexnOMRmEMb2EnK3F5ns6hHsQhHs6WnsQWjpaWlIxWsWMtRBaWjoQOntahHtaWu//Ou//vXuMYxAAKe/mzqWMtUIpEL2tnBAQMa29pRAhMQghEM7F5s69pTFSOtbm70paOnuUhFJKY/fm9+be91JaY5R7nGtaUqW9vZyEnEIxOvfm5hkQCMW1tVpjUgAQCN7mzt7v93tzWlpSa9bvzikpEIx7hKW1tRAAACEhCIyUhN7v3ko6OhkACFJjSggQGeb//869xe/v9xAQAFpKSmtaa/f3/+bv5v/374yMewAIAJycpRAZEPf37wAAADSRYJsAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAABcRAAAXEQHKJvM/AACDsElEQVR4Xu1d21LbPhOXPI5TFIOCT4BN6vd/BZ6A+bed6XfD0OaCtL0ooR1mOKQ0HYb5dleSLTtOCBAOLf4FEidxbEmrPWi1WrGXipyeOT4FzIVneQRv0oCtMfZefc56jA1ZTIcPQ84kPF9k8BSHITzzAD9mEzhKM8FYwvpbcHcXz3goBFNXgYpkrMvYzwirxzjel7lYEMaH+DxM8PlhUA0ltqFiUI3vcLwNHwkOHwzpS+fC99kUbkwnPhBINLhNI+zPv+rXFi3uiPMkSdbgf97TnI/v/rT2IO5LmYPMl93gGzhkzMOnx0HEvD68ZCFLE5RZj3ozweI+G7HsCI678G7/ONxXUmYZoHjbwAOPJYmPBwshGIdfxCigANCOvrcUWdLUZWGHsT22IdIUycH+6K8WQMnlzhRuGxHR4GfLAtSDrhkgXok0bcYVY7+nP8UU5DfhYp4CXFrIYt+ZB1QW2PD6ZoyU1AywumNovwv1dhFEgBd8ACTeLODB5hKXkQ9lBLrZCZMHt9wsgfuIt/rNfQE3+8qCH9Ti88HZELqmXIXZ85dCmYbL8KZHgmNucyaf6UW8o5c+mV6zAKnAa91oCjYpZ+pnX9XlkUGAWUjUaxCJOBU0Z+N3l/AKNh/2ShY3SMyQCY/lvle/GZ6aadmki5gB+/MtfmzVDc8q3jhUDLgZmHldvNnM7Uj05syt36wwcKGRJZnCU10z+KA4dw3M1j1oA4LjqPtu4tP6JjeflwCVlDD3uq6WXGCuNNJv2A4+wc1Sxu1GZC7cuJsaMx9qhkV3IhCDQNuGmt0OpUxuBUn0l4Ro4ivlV6OZEIJJ6hmSiQmXgh0cbao2tLQlngWEQlrlrCO/wA+2fbggnVG7ogE0br2DxGxQdHLe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"
    }
   },
   "cell_type": "markdown",
   "id": "8d202393",
   "metadata": {},
   "source": [
    "给定一组测试集样本$D$ = \\{$(x_1,y_1),(x_2,y_2), ... ,(x_m,y_m)$\\}, 其中$x_i$为样本$i$的特征值, $y_i$为样本$i$的真实标签, $f$为训练的模型, $f(x_i)$为样本i的预测标签.\n",
    "\n",
    "我们假定该类样本中label为1(正例)和0(反例):\n",
    "\n",
    "![1.png](attachment:1.png)\n",
    "\n",
    "TP(真正例):$$\\sum_{i=1}^{m}{Ⅱ(y_i=1 \\quad \\&\\&\\quad (f(x_i)= y_i))},$$\n",
    "\n",
    "FP(假正例):$$\\sum_{i=1}^{m}{Ⅱ(y_i=1 \\quad \\&\\&\\quad (f(x_i)\\neq y_i))},$$\n",
    "\n",
    "FN(假反例):$$\\sum_{i=1}^{m}{Ⅱ(y_i=0 \\quad \\&\\&\\quad (f(x_i)\\neq y_i))},$$\n",
    "\n",
    "其中查准率(precision):$$\\frac{TP}{TP+FP},$$\n",
    "\n",
    "查全率(recall):$$\\frac{TP}{TP+FN}.$$\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e507df89",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">2.4)P-R曲线: 根据模型的预测结果按正例可能性大小对样例进行排序，并逐个把样本作为正例进行预测，则可以得到查准率-查全率曲线</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c7a07f2",
   "metadata": {},
   "source": [
    "计算出所有用户的正例可能性:$P(y=1|x;w)$,并进行排序\n",
    "\n",
    "从高到低以每个用户的正例可能性为【阈值】，根据$\\hat{Y}=1$, if $P(y=1|x;w) \\geq 【阈值】$，得到一个坐标点(precision,recall)\n",
    "\n",
    "记录每个坐标点(precision,recall)的F1度量: $F1 = \\frac{2*P*R}{P+R}$\n",
    "\n",
    "最后将得到的所有(precision,recall)画成折线图"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "494dce53",
   "metadata": {},
   "source": [
    "给出一个简易的折线图的画图例子"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d11e2e1e",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'plt' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_7660/904194638.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 6\u001b[1;33m \u001b[0mplt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mprecision\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mrecall\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmarker\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'o'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      7\u001b[0m \u001b[0mplt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mxlabel\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Recall'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      8\u001b[0m \u001b[0mplt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mylabel\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Precision'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mNameError\u001b[0m: name 'plt' is not defined"
     ]
    }
   ],
   "source": [
    "thresholds = [0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95]\n",
    "recall     = [1.00, 0.97, 0.94, 0.92, 0.89, 0.85, 0.82, 0.78, 0.75, 0.70, 0.66, 0.61, 0.57, 0.53, 0.48, 0.41, 0.33, 0.21, 0.01]\n",
    "precision  = [0.60, 0.65, 0.68, 0.71, 0.74, 0.76, 0.78, 0.80, 0.82, 0.84, 0.86, 0.89, 0.9, 0.91, 0.93, 0.95, 0.96, 0.98, 1.00]\n",
    "\n",
    "\n",
    "plt.plot(precision,recall, marker='o')\n",
    "plt.xlabel('Precision')\n",
    "plt.ylabel('Recall')\n",
    "plt.title('P-R Curve')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4942b54",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">2.5)ROC曲线: 根据模型的预测结果按正例可能性大小对样例进行排序，并逐个把样本作为正例进行预测，得到一组(FPR,TPR)，进而得到ROC曲线</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3eea233a",
   "metadata": {},
   "source": [
    "其中$TPR=\\frac{TP}{TP+FN}$,$FPR=\\frac{FP}{TN+FP}.$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19fe854f",
   "metadata": {},
   "source": [
    "**<font color = blue size=4>第四部分:课堂实验</font>**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a984f25",
   "metadata": {},
   "source": [
    "我们引入了一个骨科患者的生物力学特征数据集(illness.csv)，每个患者在数据集中由六个生物力学属性表示，这些属性分别为pelvic_incidence（盆腔发病率）、pelvic_tilt numeric（骨盆倾斜）、lumbar_lordosis_angle（腰椎前凸角）、sacral_slope（骶骨斜率）、pelvic_radius（骨盆桡骨）、pelvic_radius（脊椎滑脱分级), 对应的标签则为是否为椎间盘疝气和脊椎滑脱(normal和abnormal)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ad941c3",
   "metadata": {},
   "source": [
    "该数据集共有310个样本，但并没有划分训练集和测试集."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46b03f29",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">1)导入数据集,根据数据信息定义逻辑回归的模型</span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "052a2351",
   "metadata": {},
   "outputs": [],
   "source": [
    "#your code here\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import math\n",
    "import matplotlib as mpl\n",
    "import warnings\n",
    "import random\n",
    "\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "\n",
    "df = pd.read_csv(\"illness.csv\")\n",
    "df[\"class\"] = df[\"class\"].map({\"Abnormal\": 0, \"Normal\": 1}).fillna(-1)\n",
    "\n",
    "features = df.iloc[:, :-1]\n",
    "labels = df.iloc[:, -1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efcb1743",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">2)请分别使用三种数据划分方式(留出法、交叉验证法、自助法)划分出训练集和测试集</span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "464d7c86",
   "metadata": {},
   "outputs": [],
   "source": [
    "#留出法\n",
    "#your code here\n",
    "test_ratio = 0.3\n",
    "\n",
    "test_samples_per_class = (labels.value_counts() * test_ratio).astype(int)\n",
    "\n",
    "train_data = pd.DataFrame()\n",
    "test_data = pd.DataFrame()\n",
    "\n",
    "for label, count in test_samples_per_class.items():\n",
    "    class_samples = df[df[\"class\"] == label].sample(n=count, random_state=42)\n",
    "    test_data = test_data.append(class_samples)\n",
    "    train_data = train_data.append(df[df[\"class\"] == label].drop(class_samples.index))\n",
    "\n",
    "train_features = train_data.iloc[:, :-1]\n",
    "train_labels = train_data.iloc[:, -1]\n",
    "test_features = test_data.iloc[:, :-1]\n",
    "test_labels = test_data.iloc[:, -1]\n",
    "\n",
    "# 打印训练集和测试集大小\n",
    "print(\"Train data number: \", len(train_data))\n",
    "print(\"Test data number: \", len(test_data))\n",
    "\n",
    "# 打印训练集和测试集\n",
    "print(\"Train data : \", np.array(train_data))\n",
    "print(\"Test data : \", np.array(test_data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed73ac40",
   "metadata": {},
   "outputs": [],
   "source": [
    "#交叉验证法\n",
    "#your code here\n",
    "class_0_samples = df[df[\"class\"] == 0]\n",
    "class_1_samples = df[df[\"class\"] == 1]\n",
    "\n",
    "class_0_samples = class_0_samples.sample(frac=1, random_state=42)\n",
    "class_1_samples = class_1_samples.sample(frac=1, random_state=42)\n",
    "\n",
    "k = 5\n",
    "\n",
    "train_data = []\n",
    "test_data = []\n",
    "\n",
    "for i in range(k):\n",
    "    train_fold = pd.DataFrame()\n",
    "    test_fold = pd.DataFrame()\n",
    "\n",
    "    class_0_fold_size = len(class_0_samples) // k\n",
    "    class_1_fold_size = len(class_1_samples) // k\n",
    "\n",
    "    test_fold = test_fold.append(\n",
    "        class_0_samples[i * class_0_fold_size : (i + 1) * class_0_fold_size]\n",
    "    )\n",
    "    test_fold = test_fold.append(\n",
    "        class_0_samples[i * class_1_fold_size : (i + 1) * class_1_fold_size]\n",
    "    )\n",
    "\n",
    "    train_fold = df.drop(test_fold.index)\n",
    "\n",
    "    train_fold = train_fold.sample(frac=1, random_state=42)\n",
    "    test_fold = test_fold.sample(frac=1, random_state=42)\n",
    "\n",
    "    train_data.append(train_fold)\n",
    "    test_data.append(test_fold)\n",
    "\n",
    "for i in range(k):\n",
    "    print(\"第\", i + 1, \"折的测试集: \", (test_data[i].index))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4ddd000a",
   "metadata": {},
   "outputs": [],
   "source": [
    "#自助法\n",
    "#your code here\n",
    "num_samples = df.shape[0]\n",
    "train_data = []\n",
    "test_data = []\n",
    "\n",
    "for i in range(num_samples):\n",
    "    index = random.randint(0, num_samples - 1)\n",
    "    train_data.append(df.iloc[index])\n",
    "\n",
    "# 创建测试集（排除训练集中已存在的样本）\n",
    "for _, row in df.iterrows():\n",
    "    is_in_train_data = False\n",
    "    for train_row in train_data:\n",
    "        if row.equals(train_row):\n",
    "            is_in_train_data = True\n",
    "            break\n",
    "    if not is_in_train_data:\n",
    "        test_data.append(row)\n",
    "\n",
    "# 打印训练集和测试集大小\n",
    "print(\"训练集大小: \", len(train_data))\n",
    "print(\"测试集大小: \", len(test_data))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aafd898f",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">3)请分别在三种数据划分方式(留出法、交叉验证法、自助法)所划分出训练集和测试集下训练逻辑回归模型,并测试错误率\\精度</span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1e53fad3",
   "metadata": {},
   "outputs": [],
   "source": [
    "#留出法测试精度\n",
    "#your code here\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bc44de73",
   "metadata": {},
   "outputs": [],
   "source": [
    "#交叉验证法\n",
    "#your code here\n",
    "#每次选用一个子集作为测试集，剩余k-1个子集的并集作为训练集，所以需要每轮都进行测试\n",
    "#可以使用k个轮次的精度的平均精度作为本方法的最终精度\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ffed0858",
   "metadata": {},
   "outputs": [],
   "source": [
    "#自助法测试精度\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "08220be6",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">4)按照错误率\\精度的性能指标判断出性能【最好】和性能【最差】的数据划分方式</span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9eaf7af7",
   "metadata": {},
   "outputs": [],
   "source": [
    "#your code here\n",
    "print(\"留出法精度:\")\n",
    "print(\"交叉验证法平均精度:\")\n",
    "print(\"自助法精度:\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8640fb46",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">5)在【留出法】和【自助法】中选出性能更好的数据划分方式，画出其对应的P-R曲线和ROC曲线,并计算各个点的F1度量</span>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4133f263",
   "metadata": {},
   "outputs": [],
   "source": [
    "#your code here\n",
    "#选择一种数据划分方法\n",
    "自助法\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4f9bc757",
   "metadata": {},
   "outputs": [],
   "source": [
    "#your code here\n",
    "#画出P-R曲线\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cabcc6f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "#your code here\n",
    "#画出ROC曲线\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a14b4241",
   "metadata": {},
   "source": [
    "**<font color = blue size=4>第五部分:作业提交</font>**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1774127e",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">1) 实验报告提交地址 (格式: 学号+姓名+实验四): https://send2me.cn/4-3oEngJ/Qp-icPERnYPjPQ ,\n",
    "    下周因为国庆假期所以实验课不上，本次实验报告的截止日期为10.8 14:20</span>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cdef86e2",
   "metadata": {},
   "source": [
    "<span style=\"color:purple\">2) 实验课件获取地址: https://www.jianguoyun.com/p/Dae3tZUQp5WhChiClp0FIAA</span>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
